

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;

import javax.swing.text.ChangedCharSetException;


public class Ant implements defAnt {

	//Fields
	private static final int NOFOOD = 16;
	private static final int GOTFOOD = 40;
	public static enum DIRECTION {  left,  right,
			top,  bottom, leftTop,
		leftBottom,rightTop,rightBottom };//Reihenfolge wichtig!!!!
	public static final DIRECTION [] defaultPrefDir = { DIRECTION.left, DIRECTION.right, DIRECTION.top, 
		 DIRECTION.bottom,  DIRECTION.leftTop, DIRECTION.leftBottom, DIRECTION.rightTop, DIRECTION.rightBottom };
	private static final int [] dirActions = 
		{  12,  32, 
		 21, 23, 
		 11,  13,
		 31, 33 };
	// 1.Stelle: x-Coordinate, 1->-1, 2->0, 3->1;
	// 2.Stelle: y-Coordinate, 1->-1, 2->0, 3->1.
		

	private static final DIRECTION[] TOP_PREF={DIRECTION.top,DIRECTION.rightTop,DIRECTION.leftTop,
													DIRECTION.right,DIRECTION.left,DIRECTION.rightBottom,
													DIRECTION.leftBottom,DIRECTION.bottom},
										LEFTTOP_PREF={DIRECTION.leftTop,DIRECTION.top,DIRECTION.left,
												DIRECTION.rightTop,DIRECTION.leftBottom,DIRECTION.right,
													DIRECTION.bottom,DIRECTION.rightBottom},
										LEFT_PREF={DIRECTION.left,DIRECTION.leftTop,DIRECTION.leftBottom,
												DIRECTION.top,DIRECTION.bottom,DIRECTION.rightTop,
												DIRECTION.rightBottom,DIRECTION.right},
										LEFTBOTTOM_PREF={DIRECTION.leftBottom,DIRECTION.left,DIRECTION.bottom,
												DIRECTION.leftTop,DIRECTION.rightBottom,DIRECTION.top,
												DIRECTION.right,DIRECTION.rightTop},
										BOTTOM_PREF={DIRECTION.bottom,DIRECTION.leftBottom,DIRECTION.rightBottom,
												DIRECTION.left,DIRECTION.right,DIRECTION.leftTop,
												DIRECTION.rightTop,DIRECTION.top},
										RIGHTBOTTOM_PREF={DIRECTION.rightBottom,DIRECTION.bottom,DIRECTION.right,
												DIRECTION.leftBottom,DIRECTION.rightTop,DIRECTION.left,
												DIRECTION.top,DIRECTION.leftTop},
										RIGHT_PREF={DIRECTION.right,DIRECTION.rightBottom,DIRECTION.rightTop,
												DIRECTION.bottom,DIRECTION.top,DIRECTION.leftBottom,
												DIRECTION.leftTop,DIRECTION.left},
										RIGHTTOP_PREF={DIRECTION.rightTop,DIRECTION.right,DIRECTION.top,
												DIRECTION.rightBottom,DIRECTION.leftTop,DIRECTION.bottom,
												DIRECTION.left,DIRECTION.leftBottom};
	
	
	private static Random rand = new Random();
	
	private int flag=0;
	
	//Attributes
	
	private int counter;
	private Point position;
	private PTrail pTrail;
	public int food = NOFOOD;
	private DIRECTION [] prefDir;
	private DIRECTION beforeLastDir;
	
	private AntSimulation antSim;
		
	
	//Constructor
	public Ant( Point p ,AntSimulation as){
		antSim=as;
				
		position = new Point( p );
		prefDir = defaultPrefDir.clone();
		antSim.getForestground()[p.x][p.y] *= -1;
		counter=0;
	}
	
	
	public Ant( Point p, DIRECTION dir ,AntSimulation as){
		antSim=as;
		
		position = new Point( p );
		prefDir = defaultPrefDir.clone();
		for(int i=0; i<8; i++){
			changeOrder(defaultPrefDir[rand.nextInt(defaultPrefDir.length)]);
		}
		changeOrder( dir );
		antSim.getForestground()[p.x][p.y] *= -1;
		pTrail = new PheromoneTrail(antSim);
		beforeLastDir = prefDir[7];
		
		counter=0;
	}
	
	
	/*
	Methods
	*/
	
	//getter - Methods
	
	public int getX(){
		return this.position.x;
	}
	
	public int getY(){
		return this.position.y;
	}
	
	public int getFood(){
		return this.food;
	}
	
	public PTrail getPtrail(){
		return (PheromoneTrail) this.pTrail;
	}
	
	// other Methods

	private void changeOrder( DIRECTION dir ){
		switch(dir.ordinal()){
		case 0:prefDir=LEFT_PREF;break;
		case 1:prefDir=RIGHT_PREF;break;
		case 2: prefDir=TOP_PREF;break;
		case 3: prefDir=BOTTOM_PREF;break;
		case 4: prefDir=LEFTTOP_PREF;break;
		case 5: prefDir=LEFTBOTTOM_PREF;break;
		case 6: prefDir=RIGHTTOP_PREF;break;
		case 7: prefDir=RIGHTBOTTOM_PREF;break;
		default: System.out.println("FEHLER CHANGEORDER");
		
		}
	}
	
	//version one -> 4 main doors
	private void goHomeOLD(Point position){
	
		//x>0
		if((antSim.anthill_rectangle.getMidPointX()-position.x)>0 
				&& (antSim.anthill_rectangle.getMidPointY()-position.y)>0)
				changeOrder(DIRECTION.rightBottom);
		else if(antSim.anthill_rectangle.getMidPointX()-position.x>0 
				&& antSim.anthill_rectangle.getMidPointY()-position.y<0)
				changeOrder(DIRECTION.rightTop);
		else if(antSim.anthill_rectangle.getMidPointX()-position.x>0 
				&& antSim.anthill_rectangle.getMidPointY()-position.y==0)
				changeOrder(DIRECTION.right);
		//x<0
		else if(antSim.anthill_rectangle.getMidPointX()-position.x<0 
				&& antSim.anthill_rectangle.getMidPointY()-position.y>0)
				changeOrder(DIRECTION.leftBottom);
		else if(antSim.anthill_rectangle.getMidPointX()-position.x<0 
				&& antSim.anthill_rectangle.getMidPointY()-position.y<0)
				changeOrder(DIRECTION.leftTop);
		else if(antSim.anthill_rectangle.getMidPointX()-position.x<0 
				&& antSim.anthill_rectangle.getMidPointY()-position.y==0)	
				changeOrder(DIRECTION.left);
		//x==0
		 if(antSim.anthill_rectangle.getMidPointX()-position.x==0 )
			if( antSim.anthill_rectangle.getMidPointY()-position.y<0)
				changeOrder(DIRECTION.top);
		 //if(antSim.anthill_rectangle.getMidPointX()-position.x==0 
		 else		// antSim.anthill_rectangle.getMidPointY()-position.y>0)
				changeOrder(DIRECTION.bottom);
	
/*		 //x>0
		 if((antSim.anthill_rectangle.getMidPointX()-position.x)>0 ){
			 //y>0
			 if((antSim.anthill_rectangle.getMidPointY()-position.y)>0){
				 changeOrder(DIRECTION.rightBottom);
			 }
			 //y<0
			 else if((antSim.anthill_rectangle.getMidPointY()-position.y<0)){
				 changeOrder(DIRECTION.rightTop);
			 }
			 //y==0
			 else if((antSim.anthill_rectangle.getMidPointY()-position.y==0)){
				 changeOrder(DIRECTION.right);
			 }
		 }
		 //x<0
		 else if(antSim.anthill_rectangle.getMidPointX()-position.x<0 ){
			 //y>0
			 if((antSim.anthill_rectangle.getMidPointY()-position.y)>0){
				 changeOrder(DIRECTION.leftBottom);
			 }
			 //y<0
			 else if((antSim.anthill_rectangle.getMidPointY()-position.y<0)){
				 changeOrder(DIRECTION.leftTop);
			 }
			 //y==0
			 else if((antSim.anthill_rectangle.getMidPointY()-position.y==0)){
				 changeOrder(DIRECTION.left);
			 } 
		 }
		 //x==0
		 else{
			 //y>0
			 if((antSim.anthill_rectangle.getMidPointY()-position.y)>0){
				 changeOrder(DIRECTION.bottom);
			 }
			 //y<0
			 else if((antSim.anthill_rectangle.getMidPointY()-position.y<0)){
				 changeOrder(DIRECTION.top);
			 }
		 }//else-zweig
*/		 
	}//goHome()
	
	
	private void goHome(Point nextPoint){
		//Gitter von acht feldern um ameisenhuegel->entsprechend richtung
		
		if(nextPoint.x<antSim.anthill_rectangle.x){
			if(nextPoint.y<antSim.anthill_rectangle.y){
				changeOrder(DIRECTION.rightBottom);
			}
			else if(nextPoint.y>antSim.anthill_rectangle.y2){
				changeOrder(DIRECTION.rightTop);
			}
			else{
				changeOrder(DIRECTION.right);
			}
		}
		else if(nextPoint.x>antSim.anthill_rectangle.x2){
			if(nextPoint.y<antSim.anthill_rectangle.y){
				changeOrder(DIRECTION.leftBottom);
			}
			else if(nextPoint.y>antSim.anthill_rectangle.y2){
				changeOrder(DIRECTION.leftTop);
			}
			else{
				changeOrder(DIRECTION.left);
			}
		}
		else{
			if(nextPoint.y<antSim.anthill_rectangle.y){
				changeOrder(DIRECTION.bottom);
			}
			else if(nextPoint.y>antSim.anthill_rectangle.y2){
				changeOrder(DIRECTION.top);
			}
		}
		
		
		
	}//goHome
	
	private void findWay(Point nextPoint){
		int pheromone_value=0;
		DIRECTION dir=prefDir[0];
		//String s="";
		for(int i=0;i<5;i++){
			DIRECTION actDir = prefDir[i];
			int action = Ant.dirActions[ actDir.ordinal() ];
		//	s+=actDir.ordinal()+" ";
	    	int akty = nextPoint.y + action%10 - 2;//ydiff;
	    		action/=10;
			int aktx = nextPoint.x + action - 2;//xdiff;
			if(aktx >= 0 && aktx < antSim.getSimWidth() 
					&& akty >= 0 && akty < antSim.getSimHeight() ){
				if(pheromone_value<antSim.getForestground()[aktx][akty]){
				pheromone_value=antSim.getForestground()[aktx][akty];
				dir=actDir;
				}
			}
		}
		changeOrder(dir);
	//	System.out.println(s);
	}
	
	
	
	private boolean stepDirection( Point nextPoint ){
		
		counter++;
		if( this.food==NOFOOD&&counter%10==0 ){
			findWay(nextPoint);
		}
		
		else if(this.food==GOTFOOD&&counter%30==0){
			goHome(nextPoint);
			//counter=0;
			
		}
		for( int i = 0; i < prefDir.length; i++ ){
	
			DIRECTION actDir = prefDir[i];
			int action = Ant.dirActions[ actDir.ordinal() ];
	
	    	int akty = nextPoint.y + action%10 - 2;//xdiff;
	    		action/=10;
			int aktx = nextPoint.x + action - 2;//ydiff;
		
			if( i > 0 && actDir == beforeLastDir )
				continue;
			
			if( aktx >= 0 && aktx < antSim.getSimWidth() && akty >= 0 
					&& akty < antSim.getSimHeight() 
					&& antSim.getForestground()[aktx][akty] > 0 ){
				nextPoint.x = aktx;
				nextPoint.y = akty;
				if( i > 0 )
					beforeLastDir = prefDir[0];
				changeOrder( prefDir[i] );
				return true;
			}
			
			
			
			if( aktx >= 0 && aktx < antSim.getSimWidth() 
					&& akty >= 0 && akty < antSim.getSimHeight() 
					&& antSim.getForestground()[aktx][akty] < -255 && this.food == NOFOOD ){
				this.food = GOTFOOD;
				antSim.getForestground()[aktx][akty] += GOTFOOD;
				
				if( antSim.getForestground()[aktx][akty] >= -255 )
					antSim.getForestground()[aktx][akty] = 1;
				return false;
			}
			//wenn die Ameisen am Huegel angekommen sind, geben sie das Futter ab
			if(antSim.anthill_rectangle.isAtBorder(aktx, akty) )
				this.food = NOFOOD;
		}
		return false;
	}

	
	private void validatePheromoneTrail(){
		pTrail.validate( position, this.food );
	}
	
	
	public void draw( Graphics g ){
		Color tmp;
		if( food == GOTFOOD )
			tmp = Color.red;
		else
			tmp = Color.black;
//		g.setColor(tmp);
//		g.fillRect( position.x, position.y, 1, 1);
		antSim.setUnderlayerColor(position.x, position.y, tmp.getRGB());
	}

	
	public void drawTrail( Graphics g ){
		pTrail.draw( g );
	}
	
	
	public void stepForward(){
		Point nextPoint = new Point( position );
		if( this.stepDirection( nextPoint ) ){
			
			antSim.getForestground()[position.x][position.y] *= -1;
			antSim.getForestground()[nextPoint.x][nextPoint.y] *= -1;
			position = nextPoint;
			validatePheromoneTrail();
		
		}
	}


	
	
}
